package trackcontroller;
import Track.*;
/*
*Track Controller
*
*version 1.0.0
*
*3/29/2012
*
*Copyright notice
*/

/**
 *
 * @author Josh Cohen <jmc124@pitt.edu> - Team Theta
 * @version 1.0.0, 29 Mar 2012
 */
public class TrackController{

    public static void main(String args[]){
        System.out.println("Testing Track Controller");
        System.out.println("Instantiating Track Controllers");
        TrackController one = new TrackController(0);
        TrackController two = new TrackController(1);
        TrackController three = new TrackController(2);
        System.out.println("Linking TrackControllers");
        one.setTrackController(two,null,0);
        two.setTrackController(one,three,0);
        three.setTrackController(two,null,0);
        System.out.println("Output First TrackController Configuration");
        System.out.println(one);
        System.out.println("Output Two TrackController Configuration");
        System.out.println(two);
        System.out.println("Output Three TrackController Configuration");
        System.out.println(three);
        System.out.println("Outputing First TrackController's ID");
        System.out.println(one.getID());
        System.out.println("Outputting First TrackController's lineID");
        System.out.println(one.getlineID());
        System.out.println("Outputting First TrackController's next TrackControler");
        System.out.println(one.getNext());
        System.out.println("Outputting First TrackController's previous TrackController");
        System.out.println(one.getPrevious());

        System.out.println("Testing setNext() by changing First TrackController's next to three then back");
        System.out.println(one.getNext());
        one.setNext(three);
        System.out.println(one.getNext());
        one.setNext(two);
        System.out.println(one.getNext());
        
        System.out.println("Testing setPrevious() by changing First TrackController's previous to two then back.");
        System.out.println(one.getPrevious());
        one.setPrevious(two);
        System.out.println(one.getPrevious());
        one.setPrevious(null);
        System.out.println(one.getPrevious());
        System.out.println("Testing received authority from CTC Office");
        //Continuing the test requries instantiating test blocks...
        //I can't figure out how to do this
        one.setAuthority(one.startBlock,one.endBlock,5);
        for(int i=one.startBlock;i<=one.endBlock;i++){
            System.out.println(ExternFunc.getControllerInfo(one.getlineID(),i));
        }
        System.out.println("Testing received speed from CTC Office");
        one.setSpeed(one.startBlock,one.endBlock,5);
        for(int i=one.startBlock;i<=one.endBlock;i++){
            System.out.println(ExternFunc.getControllerInfo(one.getlineID(),i));
        }
        System.out.println("Printing First TrackController's first ControllerInterface");
        System.out.println(one.toPrevious());
        System.out.println("Printing First TrackController's last ControllerInterface");
        System.out.println(one.toNext());
        
        System.out.println("Operating swith 1");
        System.out.println(one.operateSwitch(1,1));
        
        System.out.println("Operating signal 1");
        System.out.println(one.operateSignal(1,1));
        
        System.out.println("Calling First TrackController's report()");
        one.report();
        System.out.println("Pass.");
        
        System.out.println("Outputting the ControllerInterfaces for First TrackController");
        for(int i=one.startBlock;i<=one.endBlock;i++){
            System.out.println(ExternFunc.getControllerInfo(one.getlineID(),i));
        }
        System.out.println("Calling First TrackController's PLCProgram()");
        one.PLCProgram();
        System.out.println("Outputting the ControllerInterfaces for First TrackController");
        for(int i=one.startBlock;i<=one.endBlock;i++){
            System.out.println(ExternFunc.getControllerInfo(one.getlineID(),i));
        }
    }
    /**
     * @param args the command line arguments
     */
    //Stores Track Controller ID
    private int id;
    //Stores next TrackController
    private TrackController next;
    //Stores previous TrackController
    private TrackController prev;
    //Stores the lineID of the Track Controller
    private int lineID; //0 = RED, 1 = GREEN
    //Stores the initial block of the TrackController
    private int startBlock;
    //Stores the final block of the TrackController
    private int endBlock;
    
    public TrackController(int new_id){
        //Instantiates the TrackController of the given ID number
        id = new_id;
        next = null;
        prev = null;
        lineID = -1;
        
        //Set the start and end blocks based on the given ID number
        switch(id){
            case 0: startBlock = 0; endBlock = 10; break;
            case 1: startBlock = 11; endBlock = 15; break;
            case 2: startBlock = 16; endBlock = 20; break;
            default: throw new RuntimeException("Invalid Track Controller ID!");
        }
    }
    
    public TrackController(int new_id, TrackController new_next, TrackController new_prev, int new_lineID){
        id = new_id;
        next = new_next;
        prev = new_prev;
        lineID = new_lineID;
    }
    
    public void setTrackController(TrackController new_next, TrackController new_prev, int new_lineID){
        next = new_next;
        prev = new_prev;
        lineID = new_lineID;
    }
    
    private void PLCProgram(){
        int authority = 0;
        ControllerInterface temp;
        ControllerInterface curBlock;
        boolean flag = false;
        int start = startBlock;
        int end = endBlock;
           //             case 0: startBlock = 0; endBlock = 10; break;
           // case 1: startBlock = 11; endBlock = 15; break;
           // case 2: startBlock = 16; endBlock = 20; break;
            if(prev != null && !prev.toNext().TrackCircuitValue)
                authority = 1;
            while(start <= end){
                curBlock = ExternFunc.getControllerInfo(lineID, start);
                switch(id){
                case 0: for(int i=start;i<=end && !flag;i++){
                            temp = ExternFunc.getControllerInfo(lineID,i);
                            if(temp.TrackCircuitValue){
                                flag = true;
                                } else authority++;
                            }
                        break;
                case 1: for(int i=start;i<=end && !flag;i++){
                            temp = ExternFunc.getControllerInfo(lineID,i);
                            if(temp.TrackCircuitValue){
                                flag = true;
                                } else authority++;
                            }
                        break;
                case 2: for(int i=start;i<=end && !flag;i++){
                            temp = ExternFunc.getControllerInfo(lineID,i);
                            if(temp.TrackCircuitValue){
                                flag = true;
                                } else authority++;
                            }
                        break;
                default: throw new RuntimeException("Invalid TrackController ID set!!!!!!!!!!!");
            }
        if(start == end && next.toNext().TrackCircuitValue) authority++;
        curBlock.ControllerAuthority = authority;
        ExternFunc.updateControllerInfo(lineID, start, curBlock);
        if(authority == 0) operateSignal(start,-1); //Set signal to Red
        else operateSignal(start,1);                 //Set signal to Green
        if(flag) authority = 0;
        else authority = 1;
        start++;
        }
    }

    public int getID(){
        return id;
    }

    public int getlineID(){
        return lineID;
    }
    
    public TrackController getNext(){
        return next;
    }
    
    public TrackController getPrevious(){
        return prev;
    }
    
    public void setNext(TrackController new_next){
        next = new_next;
    }
    
    public void setPrevious(TrackController new_prev){
        prev = new_prev;
    }

    public Track.ControllerInterface toPrevious(){
        return ExternFunc.getControllerInfo(lineID,startBlock);
    }
    
    public Track.ControllerInterface toNext(){
        return ExternFunc.getControllerInfo(lineID,endBlock);
    }

    public void setAuthority(int startBlk, int endBlk, int authority){
        ControllerInterface set;
        for(int i=startBlk;i<=endBlk;i++){
            set = ExternFunc.getControllerInfo(lineID,i);
            set.ControllerAuthority = authority;
            ExternFunc.updateControllerInfo(lineID,i,set);
        }
    }
    
    public void setSpeed(int startBlk, int endBlk, int speedLimit){
        ControllerInterface set;
        for(int i=startBlk;i<=endBlk;i++){
            set = ExternFunc.getControllerInfo(lineID,i);
            set.CTCRequestedSpeedLimit = speedLimit;
            ExternFunc.updateControllerInfo(lineID,i,set);
        }
    }
    
    public boolean operateSwitch(int SwitchNumber, int val){
        return ExternFunc.setSwitch(SwitchNumber, lineID, val) != -1;
    }

    public boolean operateSignal(int SignalNumber, int val){
        return ExternFunc.setSignal(lineID, SignalNumber, val) == val;
    }

    public void report(){
        //Report feedback to CTC Office using Global
        //well we never actually agreed on what these variables should
        //hold so... :|
        
        //Wonder what Brendan is doing about this?
    }
    
    public String toString(){
        String result = new String("");
        result = "ID: " + id + "\tline: " + lineID + "\t" + "Start Blk: "
                + startBlock + "\t" + "End Blk: " + endBlock + "\t";
        if(next == null){
          result = result + "Next Track Controller: null\t";
        } else result = result + "Next Track Controller: " + next.id + "\t";
        if(prev == null){
            result = result + "Prev Track Controller: null\t";
        } else result = result + "Prev Track Controller: " + prev.id + "\t";
        return result;
    }
}